package com.ogms.dge.container.modules.data.converter;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ogms.dge.container.modules.common.service.DataSourceService;
import com.ogms.dge.container.modules.data.dto.InstanceDto;
import com.ogms.dge.container.modules.data.dto.SourceDto;
import com.ogms.dge.container.modules.data.entity.ServiceEntity;
import com.ogms.dge.container.modules.data.entity.SourceEntity;
import org.mapstruct.*;

import java.util.*;

/**
 * @name: ConfigConverter
 * @description: TODO
 * @author: Lingkai Shi
 * @date: 9/27/2024 10:29 PM
 * @version: 1.0
 */
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ConfigConverter {

    static ObjectMapper objectMapper = new ObjectMapper();

    @BeanMapping(ignoreByDefault = true)
    @Mapping(target = "name", source = "Name", qualifiedByName = "objectToString")
    @Mapping(target = "description", source = "Description", qualifiedByName = "objectToString")
    @Mapping(target = "tags", source = "Tags", qualifiedByName = "objectToListString")
    @Mapping(target = "category", source = "Category", qualifiedByName = "objectToString")
    @Mapping(target = "copyright", source = "Copyright", qualifiedByName = "objectToString")
    @Mapping(target = "instances", source = "Instances", qualifiedByName = "objectToListMap")
    SourceDto map2SourceDto(Map<String, Object> map);

    @BeanMapping(ignoreByDefault = true)
    @Mapping(target = "name", source = "Name", qualifiedByName = "objectToString")
    @Mapping(target = "description", source = "Description", qualifiedByName = "objectToString")
    @Mapping(target = "type", source = "Type", qualifiedByName = "objectToString")
    @Mapping(target = "config", ignore = true)
    InstanceDto map2InsDto(Map<String, Object> map);

    @Named("objectToString")
    default String objectToString(Object value) {
        if (value instanceof String) {
            return (String) value;
        } else if (value instanceof Integer) {
            return String.valueOf(value);
        }
        return null; // 或者可以抛出异常
    }

    @Named("objectToListString")
    default List<String> objectToListString(Object value) {
        if (value instanceof String) {
            return Arrays.asList((String) value);
        } else if (value instanceof List) {
            return (List<String>) value; // 强制转换
        }
        return null; // 或者可以抛出异常
    }

    @Named("objectToListMap")
    default List<Map<String, Object>> objectToListMap(Object value) {
        List<Map<String, Object>> result = new ArrayList<>();
        if (value instanceof List) {
            for (Object item : (List<?>) value) {
                Map<String, Object> map = new HashMap<>();
                // 假设 item 本身是 Map，添加转换逻辑
                if (item instanceof Map) {
                    map.putAll((Map<String, Object>) item);
                } else {
                    map.put("value", item); // 处理非 Map 类型
                }
                result.add(map);
            }
        } else if (value instanceof Map) {
            Map<String, Object> map = new HashMap<>();
            map.putAll((Map<String, Object>) value);
            result.add(map);
        }
        return result; // 或者可以返回空列表
    }

    SourceEntity sourceDto2Po(SourceDto source);

    @Mapping(target = "typeId", ignore = true)
    @Mapping(target = "config", ignore = true)
    ServiceEntity insDto2Po(InstanceDto instanceDto, @Context DataSourceService dataSourceService) throws JsonProcessingException;

    @AfterMapping
    default void handleCustomFields(SourceDto sourceDto, @MappingTarget SourceEntity sourceEntity) {
    }

    @AfterMapping
    default void handleCustomFields(InstanceDto insDto, @MappingTarget ServiceEntity serviceEntity, @Context DataSourceService dataSourceService) throws JsonProcessingException {
        QueryWrapper queryWrapper = new QueryWrapper<>().eq("name", insDto.getType());
        serviceEntity.setTypeId(dataSourceService.getOne(queryWrapper).getId());
        serviceEntity.setConfig(objectMapper.writeValueAsString(insDto.getConfig()));
    }

    @AfterMapping
    default void handleCustomFields(Map<String, Object> map, @MappingTarget InstanceDto insDto) {
        List<String> insTypes = Arrays.asList("RDB", "NoSQL", "MapService", "GeoDatabase", "DBFile", "OSS", "VectorFile", "RasterFile", "OtherFile");
        for (String type : insTypes) {
            if (map.containsKey(type)) {
                Map<String, Object> value = (Map<String, Object>) map.get(type);
                insDto.setConfig(value); // 假设 config 是一个 Object 类型的属性
                break; // 找到一个匹配后可以选择退出, 因为在validate里面已经只准一个key存在了
            }
        }
    }

}
